from __future__ import with_statement
import os
import time
import random
import string
from fabric.api import local, env, lcd

env.warn_only = True


def copy_tests(target):
    target = "../%s/" % target
    if not os.path.exists(target):
        print "Target path not found.."
        return
    local("cp ../dominion/Makefile %s" % target)
    local("cp ../dominion/card* %s" % target)
    local("cp ../dominion/randomtest*.c %s" % target)
    local("cp ../dominion/test*.h %s" % target)
    local("cp ../dominion/test*.c %s" % target)
    local("cp ../dominion/unittest*.c %s" % target)
    local("cp ../dominion/badTestDrawCard.c %s" % target)
    local("cp ../dominion/betterTestDrawCard.c %s" % target)


def test(target, type):
    target = "../%s/" % target
    if not os.path.exists(target):
        print "Target path not found.."
        return

    if type == 'unit' or type == 'all':
        local("%stestunittest1" % target)
        local("%stestunittest2" % target)
        local("%stestunittest3" % target)
        local("%stestunittest4" % target)
    if type == 'card' or type == 'all':
        local("%stestcardtest1" % target)
        local("%stestcardtest2" % target)
        local("%stestcardtest3" % target)
        local("%stestcardtest4" % target)
    if type == 'random' or type == 'all':
        local("%srandomtestcard" % target)
        local("%srandomtestadventurer" % target)
    if type == 'complete' or type == 'all':
        local("%stestdominion" % target)


def gather_cases(count):
    folder = os.path.abspath("../dominion/")
    tester = "%s/testdominion" % folder
    if not os.path.exists(tester):
        print "Tester script '%s' not found.." % tester
        return

    count = int(count)
    total = count

    def move_cov_file(folder):
        filename = ''.join(random.choice(string.letters) for i in xrange(10))
        local("mv ./dominion.c.gcov ./tarantula/%s/%s.c.gcov"
                % (folder, filename))

    with lcd(folder):
        # clear previous stats
        local("rm -f ./tarantula/passing/*")
        local("rm -f ./tarantula/failing/*")

        while count:
            print "\n------- Running case #%d -------" % (total - count + 1)

            # run case and see if it is failing or passing
            local("rm -f dominion.gcda")
            testOutput = local("./testdominion", capture=True)

            # gather code coverage
            covOutput = local("gcov ./dominion.gcda", capture=True)

            if testOutput.strip() == "OK":
                move_cov_file('passing')
                print "PASSING CASE"
            else:
                move_cov_file('failing')
                print "FAILING CASE"
            print covOutput

            # prepare for the next run
            time.sleep(1)
            count -= 1


def tarantula_stats():
    stats = {}

    def parse_cov_folder(folder):
        cnt = 0
        for root, dirs, files in os.walk(folder):  # traverse passing covs
            for f in files:
                parse_cov_file(folder, "./%s/%s" % (folder, f))
                cnt += 1
        return float(cnt)

    def parse_cov_file(casetype, filename):
        def parse_line(line):
            line = map(
                lambda x: x.strip().replace('#####', '0'),
                line.split(':'))
            return (
                int(line[0].replace('-', '0')),  # coverage count
                int(line[1]),                    # line number
                ''.join(line[2:]))               # souce code line

        print "File: %s" % filename
        with open(filename) as stream:
            lines = stream.read().splitlines()
            for line in lines:
                cnt, lno, line = parse_line(line)
                if lno not in stats:  # key is not created yet
                    stats[lno] = {
                        'passing': 0, 'failing': 0,
                        'cnt': 0, 'lno': lno, 'line': line}
                if cnt:  # our statement is covered by current test file
                    stats[lno]['cnt'] += 1
                    stats[lno][casetype] += 1

    print "\n------- Analysing PASSING Cases -------"
    cntPassing = parse_cov_folder("passing")
    print "Number of tests: %d" % cntPassing

    print "\n------- Analysing FAILING Cases -------"
    cntFailing = parse_cov_folder("failing")
    print "Number of tests: %d" % cntFailing

    # calculate tarantula metrics
    for lno, data in stats.items():
        if data['failing'] or data['passing']:  # ignore non-visited lines
            t = data['failing'] / cntFailing
            b = data['passing'] / cntPassing + data['failing'] / cntFailing
            data['tarantula'] = t / b
            #print lno, data
            if data['tarantula']:
                print "%.2f\t%d: %s" % (data['tarantula'], lno, data['line'])
